package net.uzen.office.photo.service;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;

import net.uzen.office.common.UzenOfficeConstants;
import net.uzen.office.common.util.CommonUtil;
import net.uzen.office.common.util.DocumentUtil;
import net.uzen.office.photo.dao.PhotoDao;
import net.uzen.office.photo.model.Photo;
import net.uzen.office.photo.model.PhotoComment;
import net.uzen.office.photo.model.PhotoSet;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

public class PhotoServiceImpl implements PhotoService {

	private static final String API_KEY = UzenOfficeConstants.FLICKR_API_KEY;
	private static final String SECRET = UzenOfficeConstants.FLICKR_SECRET;

	private static final Log logger = LogFactory.getLog(PhotoServiceImpl.class);

	private PhotoDao photoDao;

	public void setPhotoDao(PhotoDao photoDao) {
		this.photoDao = photoDao;
	}

	@Override
	public boolean addToPhotoSet(Photo photo) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public String createPhoto(Photo photo) {
		// TODO Auto-generated method stub
		// - Token 체크 및 갱신 ==> getAuthToken
		// 0. API_SIG 구하기
		// 1. 플리커 등록
		// 2. 리턴 메시지에서 ID 추출
		// 3. DB 등록
		// 4. 리턴 ID

		String encryptedApiSig = CommonUtil.getMD5Hash(SECRET + "api_key"
				+ API_KEY + "auth_token" + photo.getAuth_token()
				+ "content_type" + photo.getContent_type() + "description"
				+ photo.getDescription() + "hidden" + photo.getHidden()
				+ "is_family" + photo.getIs_family() + "is_friend"
				+ photo.getIs_friend() + "is_public" + photo.getIs_public()
				+ "safety_level" + photo.getSafety_level() + "tags"
				+ photo.getTags() + "title" + photo.getTitle());

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();

		// HttpClient 에서 호출할 PostMethod 설정
		PostMethod uploadPhoto = new PostMethod(
				UzenOfficeConstants.FLICKR_UPLOAD_URL);

		// 리턴할 플리커의 사진 번호
		String photoId = null;

		try {
			// 파일에 관해 시험
			MultipartFile temp = photo.getPhoto();
			logger.debug("[!] filename : " + temp.getName());
			logger.debug("[!] orignal Name : " + temp.getOriginalFilename());
			logger.debug("[!] fileSize : " + temp.getSize());

			// 파일 저장소
			File destinationDir = new File(UzenOfficeConstants.FILE_REPOSITORY);
			File destination = File.createTempFile(
					UzenOfficeConstants.FILENAME_PREFIX, temp
							.getOriginalFilename(), destinationDir);
			FileCopyUtils.copy(temp.getInputStream(), new FileOutputStream(
					destination));

			logger.debug("[!] getAbsoulutePath : "
					+ destination.getAbsolutePath());
			logger.debug("[!] getName : " + destination.getName());
			logger.debug("[!] getAbsoluteFile : "
					+ destination.getAbsoluteFile());

			FilePart fp = new FilePart("photo", new File(destination
					.getAbsolutePath()));
			fp.setCharSet("UTF-8");
			fp.setTransferEncoding("UTF-8");

			// PostMethod 에 추가 될 파라미터(StringPart, FilePart)
			Part[] parts = {
					new StringPart("api_key", API_KEY, "UTF-8"),
					new StringPart("auth_token", photo.getAuth_token(), "UTF-8"),
					new StringPart("api_sig", encryptedApiSig, "UTF-8"),
					new StringPart("title", photo.getTitle(), "UTF-8"),
					new StringPart("description", photo.getDescription(),
							"UTF-8"),
					new StringPart("tags", photo.getTags(), "UTF-8"),
					new StringPart("is_public", Integer.toString(photo
							.getIs_public()), "UTF-8"),
					new StringPart("is_friend", Integer.toString(photo
							.getIs_friend()), "UTF-8"),
					new StringPart("is_family", Integer.toString(photo
							.getIs_family()), "UTF-8"),
					new StringPart("safety_level", Integer.toString(photo
							.getSafety_level()), "UTF-8"),
					new StringPart("content_type", Integer.toString(photo
							.getContent_type()), "UTF-8"),
					new StringPart("hidden", Integer
							.toString(photo.getHidden()), "UTF-8"), fp };

			uploadPhoto.setRequestEntity(new MultipartRequestEntity(parts,
					uploadPhoto.getParams()));

			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(uploadPhoto);

			// TODO : HttpStatus 를 비교
			if (result > 0) {

				// Get the response body
				String responseBody = uploadPhoto.getResponseBodyAsString();

				logger.debug(" >> responseBody : " + responseBody);

				photoId = DocumentUtil.getXMLNodeValue(uploadPhoto
						.getResponseBodyAsStream(), "photoid");

				// TODO : 정규식으로 변경
				String token = responseBody.substring(responseBody
						.indexOf("token") + 6,
						responseBody.indexOf("/token") - 1);

				photo.setPhotoId(photoId);
				if (!photoDao.createPhoto(photo)) {
					// TODO : 에러 처리
				}

				// 임시 사진 파일 삭제
				if (!destination.delete()) {
					// TODO : 파일 삭제 오류
				}
			}

		} catch (Exception e) {

		}

		return photoId;
	}

	@Override
	public boolean createPhotoSet(PhotoSet photoSet) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean deleteFromPhotoSet(Photo photo) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean deletePhoto(Photo photo) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean deletePhotoSet(PhotoSet photoSet) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public List<Photo> getPhotoList(Map<String, Object> requestMap) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<PhotoSet> getPhotoSetList() {
		return photoDao.getPhotoSetList();
	}

	@Override
	public String modifyPhoto(Photo photo) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean modifyPhotoSet(PhotoSet photoSet) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Photo getPhoto(Photo photo) {
		return null;
	}

	@Override
	public PhotoSet getPhotoSet(PhotoSet photoSet) {
		return null;
	}

	@Override
	public String getAuthToken(Photo photo) {

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();

		// 토큰을 구한다.
		String getTokenMethodName = UzenOfficeConstants.FLICKR_GETTOKEN_METHOD;
		String tokenApiSig = SECRET + "api_key" + API_KEY + "frob"
				+ photo.getFrob() + "method" + getTokenMethodName;

		// URL 셋팅
		String getTokenUrl = "http://flickr.com/services/rest/?method="
				+ getTokenMethodName + "&api_key=" + API_KEY + "&frob="
				+ photo.getFrob() + "&api_sig="
				+ CommonUtil.getMD5Hash(tokenApiSig);

		logger.debug("[!] getTokenUrl : " + getTokenUrl);

		// getTokenMethod
		GetMethod getTokenMethod = new GetMethod(getTokenUrl);

		// 리턴할 값
		String authToken = null;

		try {

			// HttpClient 를 통해 GetMethod 를 실행
			int getTokenresult = httpClient.executeMethod(getTokenMethod);

			// TODO : HttpStatus 를 비교
			if (getTokenresult > 0) {

				// Get the response body
				String responseBody = getTokenMethod.getResponseBodyAsString();

				// TODO : 정규식으로 변경
				authToken = responseBody.substring(responseBody
						.indexOf("token") + 6,
						responseBody.indexOf("/token") - 1);

				// Token 을 셋팅한다.
				logger.debug("[!] PHOTO : After setting token > " + authToken);

			}
		} catch (Exception e) {

		}

		return authToken;
	}

	@Override
	public boolean createPhotoComment(PhotoComment comment) {
		return photoDao.createPhotoComment(comment);
	}

	@Override
	public boolean deletePhotoComment(PhotoComment comment) {
		return false;
	}

	@Override
	public boolean modifyPhotoComment(PhotoComment comment) {
		return false;
	}

	@Override
	public List<PhotoComment> getPhotoCommentList(PhotoComment comment) {
		return photoDao.getPhotoCommentList(comment);
	}
}
